/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.to.aboomy.bannersample.indicator.magicindicator;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;

import java.util.ArrayList;
import java.util.List;

/**
 * 使得MagicIndicator在FragmentContainer中使用
 *
 * @since 2020-09-29
 */
public class FragmentContainerHelper {
    private static final int NUM150 = 150;
    private List<MagicIndicator> mMagicIndicators = new ArrayList<MagicIndicator>();
    private AnimatorValue mScrollAnimator;
    private int mLastSelectedIndex;
    private int mDuration = NUM150;
    private int mInterpolator = Animator.CurveType.ACCELERATE_DECELERATE;
    private int currentPosition = 0;
    private int selectedPosition = 0;

    Animator.StateChangedListener mAnimatorListener = new Animator.StateChangedListener() {
        @Override
        public void onStart(Animator animator) {
        }

        @Override
        public void onStop(Animator animator) {
        }

        @Override
        public void onCancel(Animator animator) {
        }

        @Override
        public void onEnd(Animator animator) {
            dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE);
            mScrollAnimator = null;
        }

        @Override
        public void onPause(Animator animator) {
        }

        @Override
        public void onResume(Animator animator) {
        }
    };
    private AnimatorValue.ValueUpdateListener mAnimatorUpdateListener = new AnimatorValue.ValueUpdateListener() {
        @Override
        public void onUpdate(AnimatorValue animatorValue, float value) {
            float newValue = value;
            if (currentPosition < selectedPosition) {
                newValue = currentPosition + (selectedPosition - currentPosition) * value;
            } else if (currentPosition > selectedPosition) {
                newValue = currentPosition - (currentPosition - selectedPosition) * value;
            }
            float positionOffsetSum = newValue;
            int position = (int) positionOffsetSum;
            float positionOffset = positionOffsetSum - position;
            if (positionOffsetSum < 0) {
                position = position - 1;
                positionOffset = 1.0f + positionOffset;
            }
            dispatchPageScrolled(position, positionOffset, 0);
        }
    };

    /**
     * 构造
     */
    public FragmentContainerHelper() {
    }

    /**
     * 构造
     *
     * @param magicIndicator MagicIndicator
     */
    public FragmentContainerHelper(MagicIndicator magicIndicator) {
        mMagicIndicators.add(magicIndicator);
    }

    /**
     * IPagerIndicator支持弹性效果的辅助方法
     *
     * @param positionDataList positionDataList
     * @param index index
     * @return PositionData
     */
    public static PositionData getImitativePositionData(List<PositionData> positionDataList, int index) {
        if (index >= 0 && index <= positionDataList.size() - 1) { // 越界后，返回假的PositionData
            return positionDataList.get(index);
        } else {
            PositionData result = new PositionData();
            PositionData referenceData;
            int offset;
            if (index < 0) {
                offset = index;
                referenceData = positionDataList.get(0);
            } else {
                offset = index - positionDataList.size() + 1;
                referenceData = positionDataList.get(positionDataList.size() - 1);
            }
            result.setmLeft(referenceData.getmLeft() + offset * referenceData.width());

            result.setmTop(referenceData.getmTop());
            result.setmRight(referenceData.getmRight() + offset * referenceData.width());
            result.setmBottom(referenceData.getmBottom());
            result.setmContentLeft(referenceData.getmContentLeft() + offset * referenceData.width());
            result.setmContentTop(referenceData.getmContentTop());
            result.setmContentRight(referenceData.getmContentRight() + offset * referenceData.width());
            result.setmContentBottom(referenceData.getmContentBottom());
            return result;
        }
    }

    /**
     * handlePageSelected
     *
     * @param selectedIndex int
     */
    public void handlePageSelected(int selectedIndex) {
        handlePageSelected(selectedIndex, true);
    }

    /**
     * handlePageSelected
     *
     * @param selectedIndex selectedIndex
     * @param isSmooth isSmooth
     */
    public void handlePageSelected(int selectedIndex, boolean isSmooth) {
        if (mLastSelectedIndex == selectedIndex) {
            return;
        }
        if (isSmooth) {
            if (mScrollAnimator == null || !mScrollAnimator.isRunning()) {
                dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_SETTLING);
            }
            dispatchPageSelected(selectedIndex);
            if (mScrollAnimator != null) {
                mScrollAnimator.cancel();
                mScrollAnimator = null;
            }
            mScrollAnimator = new AnimatorValue();

            mScrollAnimator.setValueUpdateListener(mAnimatorUpdateListener);
            mScrollAnimator.setStateChangedListener(mAnimatorListener);
            mScrollAnimator.setCurveType(mInterpolator);
            mScrollAnimator.setDuration(mDuration);
            mScrollAnimator.start();
            currentPosition = mLastSelectedIndex;
            selectedPosition = selectedIndex;
        } else {
            dispatchPageSelected(selectedIndex);
            if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
                dispatchPageScrolled(mLastSelectedIndex, 0.0f, 0);
            }
            dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE);
            dispatchPageScrolled(selectedIndex, 0.0f, 0);
        }
        mLastSelectedIndex = selectedIndex;
    }

    /**
     * 设置时间
     *
     * @param duration duration
     */
    public void setDuration(int duration) {
        mDuration = duration;
    }

    /**
     * setInterpolator
     *
     * @param interpolator interpolator
     */
    public void setInterpolator(int interpolator) {
        mInterpolator = interpolator;
    }

    /**
     * attachMagicIndicator
     *
     * @param magicIndicator magicIndicator
     */
    public void attachMagicIndicator(MagicIndicator magicIndicator) {
        mMagicIndicators.add(magicIndicator);
    }

    private void dispatchPageSelected(int pageIndex) {
        for (MagicIndicator magicIndicator : mMagicIndicators) {
            magicIndicator.onPageSelected(pageIndex);
        }
    }

    private void dispatchPageScrollStateChanged(int state) {
        for (MagicIndicator magicIndicator : mMagicIndicators) {
            magicIndicator.onPageScrollStateChanged(state);
        }
    }

    private void dispatchPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        for (MagicIndicator magicIndicator : mMagicIndicators) {
            magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }
    }
}
